from flask import Flask, render_template, request, jsonify, session, redirect, url_for
import json
import os
import hashlib
from functools import wraps
from collections import deque

app = Flask(__name__)
app.secret_key = 'your-secret-key-here'  # 用于session加密
CONFIG_FILE = 'config.json'
LOG_FILE = 'logs/padbot.log'

def get_md5(text):
    return hashlib.md5(text.encode('utf-8')).hexdigest()

def verify_login(username, password):
    try:
        with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
            config = json.load(f)
            if 'auth' not in config:
                return False
            auth = config['auth']
            if username not in auth:
                return False
            stored_password = auth[username]
            return stored_password == get_md5(password)
    except Exception:
        return False

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if 'logged_in' not in session:
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    return decorated_function

def validate_config(config):
    """验证配置文件格式"""
    required_fields = ['me', 'fromUid', 'toUids', 'whiteRooms', 'whitePersons', 'forwarders']
    
    # 检查必需字段
    for field in required_fields:
        if field not in config:
            raise ValueError(f"Missing required field: {field}")
    
    # 验证me字段
    if not isinstance(config['me'], dict) or 'name' not in config['me'] or 'wxid' not in config['me']:
        raise ValueError("Invalid 'me' field format")
    
    # 验证列表字段
    list_fields = ['fromUid', 'toUids', 'whiteRooms', 'whitePersons']
    for field in list_fields:
        if not isinstance(config[field], list):
            raise ValueError(f"'{field}' must be a list")
    
    # 验证forwarders
    if not isinstance(config['forwarders'], list):
        raise ValueError("'forwarders' must be a list")
    
    for forwarder in config['forwarders']:
        required_forwarder_fields = ['name', 'description', 'enabled', 'sourceIds', 'targetIds', 'filters']
        for field in required_forwarder_fields:
            if field not in forwarder:
                raise ValueError(f"Forwarder missing required field: {field}")
        
        if not isinstance(forwarder['filters'], dict):
            raise ValueError("Forwarder 'filters' must be a dictionary")
        
        if 'messageTypes' not in forwarder['filters']:
            raise ValueError("Forwarder filters missing 'messageTypes'")
    
    return True

def load_app_config():
    """加载应用配置文件"""
    try:
        with open('app.conf', 'r') as f:
            return json.load(f)
    except Exception as e:
        print(f"加载应用配置文件时出错: {str(e)}")
        return None

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        
        if verify_login(username, password):
            session['logged_in'] = True
            session['username'] = username
            return redirect(url_for('index'))
        else:
            return render_template('login.html', error='Invalid credentials')
    
    return render_template('login.html')

@app.route('/logout')
def logout():
    session.pop('logged_in', None)
    return redirect(url_for('login'))

@app.route('/')
@login_required
def index():
    return render_template('config.html', username=session.get('username'))

@app.route('/logs')
@login_required
def logs():
    return render_template('logs.html', username=session.get('username'), logs=get_recent_logs())

@app.route('/api/config', methods=['GET'])
@login_required
def get_config():
    try:
        with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
            config = json.load(f)
        return jsonify(config)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/config', methods=['POST'])
@login_required
def save_config():
    try:
        new_config = request.get_json()
        
        # 验证新配置
        validate_config(new_config)
        
        # 备份现有配置
        if os.path.exists(CONFIG_FILE):
            with open(CONFIG_FILE + '.backup', 'w', encoding='utf-8') as f:
                with open(CONFIG_FILE, 'r', encoding='utf-8') as current:
                    f.write(current.read())
        
        # 保存新配置
        with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
            json.dump(new_config, f, ensure_ascii=False, indent=4)
        
        return jsonify({'message': 'Configuration saved successfully'})
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/api/logs')
@login_required
def get_logs():
    return jsonify({'logs': get_recent_logs()})

@app.route('/api/change-password', methods=['POST'])
@login_required
def change_password():
    try:
        data = request.get_json()
        current_password = data.get('currentPassword')
        new_password = data.get('newPassword')
        username = session.get('username')

        if not current_password or not new_password or not username:
            return jsonify({'error': 'Missing required fields'}), 400

        # 验证当前密码
        if not verify_login(username, current_password):
            return jsonify({'error': 'Current password is incorrect'}), 400

        # 读取配置文件
        with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
            config = json.load(f)

        # 更新密码
        config['auth'][username] = get_md5(new_password)

        # 保存配置文件
        with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
            json.dump(config, f, ensure_ascii=False, indent=4)

        return jsonify({'message': 'Password changed successfully'})
    except Exception as e:
        return jsonify({'error': str(e)}), 500

def get_recent_logs(max_lines=100):
    logs = []
    try:
        if os.path.exists(LOG_FILE):
            with open(LOG_FILE, 'r', encoding='utf-8') as f:
                # 使用deque来保存最后max_lines行
                recent_logs = deque(f, max_lines)
                logs = list(recent_logs)
        return logs
    except Exception as e:
        return [f"Error reading logs: {str(e)}"]

if __name__ == '__main__':
    app_config = load_app_config()
    if app_config and 'web_service' in app_config:
        web_config = app_config['web_service']
        host = web_config.get('host', '0.0.0.0')
        port = web_config.get('port', 5100)
        debug = web_config.get('debug', True)
        app.run(host=host, port=port, debug=debug)
    else:
        print("无法加载应用配置，使用默认配置")
        app.run(debug=True, port=5100)
